use rusty_v8 as v8;

fn main() {
  // Initialize V8.
  let platform = v8::new_default_platform().unwrap();
  v8::V8::initialize_platform(platform);
  v8::V8::initialize();

  // Create a new Isolate and make it the current one.
  let isolate = &mut v8::Isolate::new(v8::CreateParams::default());

  // Create a stack-allocated handle scope.
  let handle_scope = &mut v8::HandleScope::new(isolate);

  // Create a new context.
  let context = v8::Context::new(handle_scope);

  // Enter the context for compiling and running the hello world script.
  let scope = &mut v8::ContextScope::new(handle_scope, context);

  // Create a string containing the JavaScript source code.
  let code = v8::String::new(scope, "'Hello' + ' World!'").unwrap();

  // Compile the source code.
  let script = v8::Script::compile(scope, code, None).unwrap();
  // Run the script to get the result.
  let result = script.run(scope).unwrap();

  // Convert the result to a string and print it.
  let result = result.to_string(scope).unwrap();
  println!("{}", result.to_rust_string_lossy(scope));

  // Use the JavaScript API to generate a WebAssembly module.
  //
  // |bytes| contains the binary format for the following module:
  //
  //     (func (export "add") (param i32 i32) (result i32)
  //       get_local 0
  //       get_local 1
  //       i32.add)
  //
  let c_source = r#"
        let bytes = new Uint8Array([
          0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, 0x01, 0x07, 0x01,
          0x60, 0x02, 0x7f, 0x7f, 0x01, 0x7f, 0x03, 0x02, 0x01, 0x00, 0x07,
          0x07, 0x01, 0x03, 0x61, 0x64, 0x64, 0x00, 0x00, 0x0a, 0x09, 0x01,
          0x07, 0x00, 0x20, 0x00, 0x20, 0x01, 0x6a, 0x0b
        ]);
        let module = new WebAssembly.Module(bytes);
        let instance = new WebAssembly.Instance(module);
        instance.exports.add(3, 4);
      "#;
  // Create a string containing the JavaScript source code.
  let source = v8::String::new(scope, c_source).unwrap();

  // Compile the source code.
  let script = v8::Script::compile(scope, source, None).unwrap();

  // Run the script to get the result.
  let result = script.run(scope).unwrap();

  // Print the result.
  let result = result.to_uint32(scope).unwrap();
  println!("3 + 4 = {}", result.value());
}
